home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / inventor / inventorTemplates1.1.2 / PlayClass.c++ < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  22.6 KB  |  995 lines

  1. /*
  2.  * Copyright (C) 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. #include <stdio.h>
  18. #include <fcntl.h>
  19. #include <errno.h>
  20. #include <sys/types.h>
  21. #include <sys/stat.h>
  22. #include <sys/prctl.h>
  23. #include <sys/wait.h>
  24. #include <malloc.h>
  25. #include <math.h>
  26. #include <string.h>
  27. #include <getopt.h>
  28. #include <CC/osfcn.h>
  29. #include <signal.h>
  30. #include <invent.h>
  31.  
  32. #include "PlayClass.h"
  33.  
  34. static void quietAFerror(long, const char *);
  35. static void quietALerror(long, const char *, ...);
  36.  
  37.  
  38. /*
  39.  * local defines
  40.  */
  41. #ifndef FALSE
  42. #define FALSE (0)
  43. #define TRUE (!FALSE)
  44. #endif
  45. #ifndef ABS
  46. #define ABS(a)        ((a)>0.0?(a):-(a))
  47. #endif
  48. #ifndef MIN
  49. #define    MIN(a, b)    ((a)<(b)?(a):(b))
  50. #endif
  51. #ifndef MAX
  52. #define    MAX(a, b)    ((a)>(b)?(a):(b))
  53. #endif
  54. #define    RANGE(a, b1, b2)            \
  55.                         \
  56.         ((b1)<(b2)?                \
  57.          ((a)<(b1)?                \
  58.           (b1):                \
  59.           ((a)>(b2)?            \
  60.                (b2):(a))):        \
  61.          ((a)<(b2)?                \
  62.           (b2):                \
  63.           ((a)>(b1)?            \
  64.                (b1):(a))))
  65.  
  66. #ifndef INTERP
  67. #define INTERP(x1, x2, a) ((a)*(x2)+(1.0-(a))*(x1))
  68. #endif
  69.  
  70.  
  71. PlayClass::PlayClass(char *mname)
  72. {
  73.     myname = mname;
  74.     rude    = TRUE;
  75.     quiet  = FALSE;
  76.     timed = FALSE;
  77.     verbose = FALSE;
  78.     NoDone = FALSE;
  79. #ifdef DEBUG
  80.     verbose = TRUE;
  81. #endif
  82.     caught_sigint = FALSE;
  83.     paused = FALSE;
  84.     filename = NULL;
  85.     doneCallback = NULL;
  86.     loop = FALSE;
  87.     fading_in = FALSE;
  88.     fading_out = FALSE;
  89.     in_time = 0.0;
  90.     out_time = 0.0;
  91.     fade_level = 0.0;
  92.     max_level = 1.0;
  93.     isLive = FALSE;
  94.     isDone = TRUE;
  95.     sproced = FALSE;
  96.     signal(SIGCLD,SIG_IGN); /* ensure no zombie child processes */
  97. }
  98.  
  99.  
  100. /*
  101.  * attenuatesamps
  102.  *
  103.  *        tristram, 1993
  104.  *
  105.  * put a ramp on a buffer of samples, starting at the current fade_level
  106.  * at a slope of 1 / fade_time.
  107.  *
  108.  * mode = 0 ==> fade in
  109.  * mode = 1 ==> fade out
  110.  * mode = 2 ==> don't adjust fade_level (just use max_level)
  111.  *
  112.  * this function has the side effect of setting fade_level
  113.  *
  114.  */
  115.  
  116. void
  117. PlayClass::attenuatesamps( void * sampbuf, long sampsize, long nsamps,
  118.                double secs_per_buf,
  119.            double max_level,
  120.            double * fade_level,
  121.            double fade_time,
  122.            int mode ) {
  123.  
  124.   int i;
  125.  
  126. #ifdef DEBUG
  127. fprintf(stderr, "attenuating max_level = %f, fade_level = %f, fade_time = %f\n", max_level, *fade_level, fade_time);
  128. #endif
  129.  
  130.   if ( verbose ) printf( "fade_level = %f\n", *fade_level );
  131.  
  132.   if (( mode != 2 ) && ( fade_time == 0.0 )) {
  133.     if ( *fade_level == 0.0 ) *fade_level = 1.0;
  134.     else              *fade_level = 0.0;
  135.     return;
  136.   }
  137.  
  138.   for ( i = 0; i < nsamps; i++ ) {
  139.     switch ( sampsize ) {
  140.     case AL_SAMPLE_8:
  141.       ((char *)sampbuf)[ i ] *= max_level * *fade_level;
  142.       break;
  143.     case AL_SAMPLE_16:
  144.       ((short *)sampbuf)[ i ] *= max_level * *fade_level;
  145.       break;
  146.     case AL_SAMPLE_24:
  147.       ((long *)sampbuf)[ i ] *= max_level * *fade_level;
  148.       break;
  149.     }
  150.     if ( mode != 2 ) {
  151.       if ( fade_time == 0.0 ) {
  152.     if ( mode == 0 ) { /* fading in */
  153.       *fade_level = 1.0;
  154.     } else { /* fading  out */
  155.       *fade_level = 0.0;
  156.     }
  157.       } else {
  158.     *fade_level += ( mode == 0 ? 1.0 : -1.0 )
  159.       * secs_per_buf / (fade_time * nsamps);
  160.     *fade_level = RANGE( *fade_level, 0.0, 1.0 );
  161.       }
  162.     }
  163.   }
  164. }
  165.  
  166.  
  167.  
  168. int PlayClass::beginPlaying()
  169. {
  170. #ifdef DEBUG
  171.   fprintf(stderr, "beginPlaying()\n");
  172. #endif
  173.     AFfilehandle audio_file;
  174.     ALconfig audio_port_config;
  175.     ALport audio_port;
  176.     int errseen = 0;
  177.     int result;
  178.  
  179. #ifdef DEBUG
  180.   fprintf(stderr, "checkpoint 1()\n");
  181. #endif
  182.  
  183.   if (isDone) isDone = FALSE;
  184.   else return -1;
  185.  
  186.   isLive = TRUE;
  187.   fading_in = FALSE;
  188.   fading_out = FALSE;
  189.   fade_level = 0.0;
  190.   caught_sigint = FALSE;
  191.  
  192.   max_level = RANGE( max_level, 0.0, 1.0 );
  193.   if (in_time == 0.0) fade_level = 1.0;
  194.  
  195. #ifdef DEBUG
  196.   fprintf(stderr, "new max_level is %f\n", max_level);
  197. #endif
  198.  
  199.     if ((fd = open(filename, O_RDONLY)) < 0)
  200.       {
  201.       if (!quiet)
  202.         {
  203.                 fprintf(stderr, "%s: failed to open file '%s' %s\n",
  204.                      myname, filename, strerror(errno));
  205.             }
  206.             errseen = 1;
  207.       }
  208.     /*
  209.      * test the file descriptor to see whether we can attach an audio
  210.      *    file handle to it
  211.      */
  212.     else if (AFidentifyfd(fd) < 0) 
  213.       {
  214.       if (!quiet)
  215.         {
  216.                 fprintf(stderr,"%s: '%s' not an AIFF-C or AIFF file\n",
  217.                      myname, filename);
  218.             }
  219.             errseen = 1;
  220.       }
  221.     /*
  222.      * attach an audio file handle to the file descriptor
  223.      */
  224.     else if ((audio_file = AFopenfd(fd, "r", AF_NULL_FILESETUP)) 
  225.          == AF_NULL_FILEHANDLE)
  226.       {
  227.       if (!quiet)
  228.             {
  229.                 fprintf(stderr, "%s: failed to open file '%s'\n", 
  230.             myname, filename);
  231.             }
  232.       errseen = 1;
  233.       }
  234.     else 
  235.       {
  236.       result = init_audio(audio_file, &audio_port, &audio_port_config);
  237. #ifdef DEBUG
  238.   fprintf(stderr, "result = %d\n", result);
  239. #endif
  240.       if (result != -1)
  241.             {
  242. #ifdef DEBUG
  243.   fprintf(stderr, "playing audio", result);
  244. #endif
  245.                 play_audio_samps(audio_file, audio_port, audio_port_config);
  246.             } else {
  247.         errseen = 1;
  248.         }
  249.       AFclosefile(audio_file);
  250. #ifdef DEBUG
  251.   fprintf(stderr, "freeing config... ");
  252. #endif
  253.       ALfreeconfig(audio_port_config);
  254. #ifdef DEBUG
  255.   fprintf(stderr, "done\n");
  256. #endif
  257.       if (result != -1) 
  258.             {
  259.             ALcloseport(audio_port);
  260.             }
  261.       free(sampbuf);
  262.       }
  263.     if (errseen) {
  264. #ifdef DEBUG
  265.       fprintf(stderr, "error! returning -1\n");
  266. #endif
  267.     isDone = 1;
  268.         if (sproced) exit(0);
  269.     return -1;
  270.       }
  271.     else {
  272. #ifdef DEBUG
  273.     fprintf(stderr, "done\n");
  274. #endif
  275.     if (doneCallback) {
  276. #ifdef DEBUG
  277.         fprintf(stderr, "calling doneCallback\n");
  278. #endif
  279.         doneCallback(userData, this);
  280.     }
  281.     isDone = 1;
  282.     if (sproced) {
  283. #ifdef DEBUG
  284.     fprintf(stderr, "exiting zero");
  285. #endif
  286.     exit(0);
  287.     }
  288. #ifdef DEBUG
  289.     fprintf(stderr, "after exit(0)");
  290. #endif
  291.     return 1;
  292.     }
  293. }
  294.  
  295. /*
  296.  * initialize audio port and global state of IRIS Audio Processor
  297.  */
  298. int 
  299. PlayClass::init_audio(AFfilehandle audio_file, ALport *audio_port,
  300.               ALconfig *ap_config)
  301. {
  302. #ifdef DEBUG
  303.   fprintf(stderr, "init_audio(...)\n");
  304. #endif
  305. //    long pvbuf[4];
  306.     long pvbuf[2];
  307.     long audio_rate;
  308.     long samp_type;
  309.     long samp_wordsize;    
  310.     long vers;
  311.  
  312.     samps_per_frame   = (int) AFgetchannels(audio_file, AF_DEFAULT_TRACK);
  313.     file_rate         = AFgetrate(audio_file, AF_DEFAULT_TRACK);
  314.     compression       = AFgetcompression(audio_file, AF_DEFAULT_TRACK);
  315.     filefmt           = AFgetfilefmt(audio_file, &vers);
  316.  
  317.     AFgetsampfmt(audio_file, AF_DEFAULT_TRACK, &samp_type, &bits_per_samp);
  318.  
  319.     /*
  320.      * need to determine whether audio is in use. if not, then we
  321.      * can just go ahead and be "rude."
  322.      */
  323.     pvbuf[0] = AL_OUTPUT_COUNT;
  324. //    pvbuf[2] = AL_MONITOR_CTL;
  325. //    ALgetparams(AL_DEFAULT_DEVICE, pvbuf, 4);
  326.     ALgetparams(AL_DEFAULT_DEVICE, pvbuf, 2);
  327.  
  328. //    if ((pvbuf[1] == 0) && (pvbuf[3] == AL_MONITOR_OFF)) {
  329.     if (pvbuf[1] == 0) {
  330.         rude = 1;
  331.     }
  332.     
  333.     /* 
  334.      * decide on output rate for the audio hardware
  335.      */
  336.     switch((long)file_rate)
  337.     {
  338.         case 48000: audio_rate = AL_RATE_48000; frames_per_sec = 48000; break;
  339.         case 44100: audio_rate = AL_RATE_44100; frames_per_sec = 44100; break;
  340.         case 32000: audio_rate = AL_RATE_32000; frames_per_sec = 32000; break;
  341.         case 22050: audio_rate = AL_RATE_22050; frames_per_sec = 22050; break;
  342.         case 16000: audio_rate = AL_RATE_16000; frames_per_sec = 16000; break;
  343.         case 11025: audio_rate = AL_RATE_11025; frames_per_sec = 11025; break;
  344.         case 8000: audio_rate = AL_RATE_8000; frames_per_sec = 8000; break;
  345.         default:
  346.             if (!quiet)
  347.             {
  348.                 fprintf(stderr, "%s: can't play data at sample rate %f\n",
  349.                   myname, file_rate);
  350.             }
  351.             frames_per_sec = 44100; /* pick some arbitrary rate */
  352.             audio_rate = AL_RATE_44100;
  353.     }
  354.     /*
  355.      * determine the current output rate
  356.      */
  357.     pvbuf[0] = AL_OUTPUT_RATE;
  358.     ALgetparams(AL_DEFAULT_DEVICE, pvbuf, 2);
  359.     /*
  360.      * if the rates are the same, all is well. if not, then we need to proceed
  361.      * in a either a "rude" or "polite" manner.
  362.      */
  363.     if (pvbuf[1] != audio_rate)
  364.     {
  365.     if (rude)
  366.     {
  367.         pvbuf[1] = audio_rate;
  368.         ALsetparams(AL_DEFAULT_DEVICE, pvbuf, 2);
  369.     }
  370.     else /*polite*/
  371.     {
  372.         double tmp_rate;
  373.         
  374.             if (!quiet)
  375.             {
  376.             switch (pvbuf[1])
  377.                 {
  378.                     case AL_RATE_48000: tmp_rate = 48000; break;
  379.                     case AL_RATE_44100: tmp_rate = 44100; break;
  380.                     case AL_RATE_32000: tmp_rate = 32000; break;
  381.                     case AL_RATE_22050: tmp_rate = 22050; break;
  382.                     case AL_RATE_16000: tmp_rate = 16000; break;
  383.                     case AL_RATE_11025: tmp_rate = 11025; break;
  384.                     case AL_RATE_8000:  tmp_rate = 8000;  break;
  385.                  }
  386.                  fprintf(stderr,
  387.         "%s: '%s': adjust system output rate (currently %6.1f Hz)\n",
  388.                     myname, filename, tmp_rate);
  389.  
  390.             }
  391.         }
  392.     }
  393.     
  394.  
  395.     /*
  396.      * decide what size blocks of samples we should read from the
  397.      * input file and pass to ALwritesamps
  398.      */
  399.     if (bits_per_samp <= 8)
  400.     {
  401.        bytes_per_samp = 1;
  402.        samp_wordsize  = AL_SAMPLE_8;
  403.     }
  404.     else if (bits_per_samp <= 16)
  405.     {
  406.        bytes_per_samp = 2;
  407.        samp_wordsize  = AL_SAMPLE_16;
  408.     }
  409.     else if (bits_per_samp <= 24)
  410.     {
  411.        bytes_per_samp = 4;
  412.        samp_wordsize  = AL_SAMPLE_24;
  413.     }
  414.     else
  415.     {
  416.         if (!quiet)
  417.         { 
  418.             fprintf(stderr, "%s: %s: error can't play %d bit samples\n",
  419.                 myname, filename, bits_per_samp);
  420.         }
  421.         return(-1);
  422.     }
  423.  
  424.     if ((samps_per_frame != 1) && (samps_per_frame!= 2))
  425.     {
  426.        if (!quiet)
  427.        {
  428.           fprintf(stderr, "%s: %s: error can't play %d channel sample data\n",
  429.              myname, filename, samps_per_frame);
  430.        }
  431.        return(-1);
  432.     }
  433.  
  434.     /*
  435.      * make the buffer large enough to hold 1/2 sec of audio frames
  436.      * we add one to frames_per_sec before we divide in order to
  437.      * correctly handle the 11025 case
  438.      */
  439.     secs_per_frame = 1.0 / ((double)frames_per_sec);
  440. //    frames_per_buf = (frames_per_sec+1)/2;
  441.   /* ok, I changed this so that now Im holding 1/4 sec of audio frames */
  442.     frames_per_buf = (int) (frames_per_sec+15)/20;
  443.  
  444.     samps_per_buf = frames_per_buf * samps_per_frame;
  445.     bytes_per_buf = samps_per_buf * bytes_per_samp;
  446.     secs_per_buf  = secs_per_frame * frames_per_buf;
  447.  
  448.     sampbuf = (char *) malloc(bytes_per_buf);
  449.  
  450.     /*
  451.      * configure and open audio port
  452.      */
  453.     *ap_config = ALnewconfig();
  454.     ALsetwidth(*ap_config, samp_wordsize);
  455.     ALsetchannels(*ap_config, samps_per_frame);
  456.  
  457.     /*
  458.      * make the ring buffer large enough to hold 1 sec of audio samples
  459.      */
  460.     ALsetqueuesize(*ap_config, samps_per_buf*2);
  461.     *audio_port = ALopenport(myname, "w", *ap_config);
  462.  
  463.     if (*audio_port != NULL) {
  464.     return (1);
  465.     }
  466.     else {
  467.     return (-1);
  468.     }
  469.  
  470. }
  471.  
  472.  
  473. /*
  474.  * play audio sample data through the output port
  475.  */
  476. int
  477. PlayClass::play_audio_samps(AFfilehandle audio_file, ALport audio_port,
  478.                 ALconfig ap_config)
  479. {
  480. #ifdef DEBUG
  481.   fprintf(stderr, "play_audio_samps(...)\n");
  482. #endif
  483.     int num_bufs;
  484.     int leftover_bytes;
  485.     int leftover_samps;
  486.     int leftover_frames;
  487.     long samp_wordsize;
  488.     int samp_count;
  489.     int frame_count;
  490.     double sec_count;
  491.     int i;
  492.     int samples_read;
  493.     int frames_read;
  494.     int done;
  495.     int shortread;
  496.     int total_frames;    
  497.     int total_samps;
  498.     int total_samp_bytes;
  499.  
  500.     char compressionname[10];
  501.     float fileplayingtime;
  502.  
  503.     sec_count = 0.0;
  504.  
  505.     /*
  506.      * figure out how many reads we have to do
  507.      */
  508.     total_frames    =  (int) AFgetframecnt(audio_file, AF_DEFAULT_TRACK);
  509.     total_samps      =  total_frames * samps_per_frame;
  510.     total_samp_bytes =  total_samps * bytes_per_samp;
  511.     num_bufs         = total_samp_bytes / bytes_per_buf;
  512.     leftover_bytes   = total_samp_bytes % bytes_per_buf;
  513.     leftover_samps   = leftover_bytes / bytes_per_samp;
  514.     leftover_frames  = leftover_samps / samps_per_frame;
  515.  
  516.     samp_wordsize = ALgetwidth(ap_config);
  517.  
  518.     if (!quiet)
  519.     {
  520.         fileplayingtime = (float)total_frames / (float)frames_per_sec;
  521.         switch (compression)
  522.         {
  523.             default:
  524.             case AF_COMPRESSION_NONE: 
  525.                     strcpy(compressionname, "");
  526.                     break;
  527.             case AF_COMPRESSION_G722:
  528.                     strcpy(compressionname, "G.722 -->");
  529.                     break;
  530.             case AF_COMPRESSION_G711_ALAW:
  531.                     strcpy(compressionname, "A-law -->");
  532.                     break;
  533.             case AF_COMPRESSION_G711_ULAW:
  534.                     strcpy(compressionname, "u-law -->");
  535.                     break;
  536.         }
  537.     }
  538.     if (verbose) 
  539.     {
  540.     printf("%s: '%s' %6.3f sec %7.1f Hz %6s %s %d-bit %s\n",
  541.            myname,
  542.            filename,
  543.            fileplayingtime,
  544.            file_rate,
  545.            samps_per_frame == 1 ? "mono" : "stereo",
  546.            compressionname,
  547.            bits_per_samp,
  548.            filefmt == AF_FILE_AIFFC ? "AIFF-C" : "AIFF"
  549.        );
  550.         printf( "        total sample frames       = %d (%d bytes)\n",
  551.                     total_frames, total_samp_bytes);
  552.         printf( "        play data using blocksize = %d sample frames\n",
  553.                     frames_per_buf);
  554.         printf( "        total blocks              = %d (%d extra frames)\n",
  555.                     num_bufs, leftover_frames); 
  556.     }
  557.  
  558.     sec_count = 0.0;
  559.  top:
  560.  
  561.     /*
  562.      * move the fileptr to the beginning of the sample data
  563.      */
  564.     AFseekframe(audio_file, AF_DEFAULT_TRACK, 0);
  565.  
  566.     /*
  567.      * note that there may be some pad bytes following the valid samples -
  568.      * for example, the sample data area may be padded so that the valid 
  569.      * samples begin on a block boundary and the sample area ends on a block
  570.      * boundary (where blocksize is specified by the user)
  571.      */
  572.     done        = 0;
  573.     shortread   = 0;
  574.     samp_count  = 0;
  575.     frame_count = 0; 
  576. //    sec_count   = 0.0;
  577.  
  578.     for (i=0; i<num_bufs; i++)
  579.     {
  580.         samp_count  += samps_per_buf;
  581.         frame_count += frames_per_buf;
  582.         sec_count   += secs_per_buf;
  583.  
  584.         if (verbose) 
  585.         {
  586.             printf("        %d sample frames  %6.3f secs\n",
  587.                 frame_count, sec_count); 
  588.         }
  589.         if ((frames_read 
  590.             = (int) AFreadframes(audio_file, AF_DEFAULT_TRACK, 
  591.                           sampbuf, frames_per_buf)) < frames_per_buf)
  592.         {
  593.             if (!quiet)
  594.             {
  595.                 fprintf(stderr, 
  596.          "%s: warning short read for %s: expected %d frames, got %d frames\n",
  597.                         myname, filename, frames_per_buf, frames_read);
  598.             }
  599. //            done++;
  600.         shortread++;
  601.         }
  602.         samples_read = frames_read * samps_per_frame;
  603.  
  604.     if ( timed && ( sec_count - in_time > play_time )) {
  605.       fading_in = FALSE;
  606.       fading_out = TRUE;
  607.     }
  608.  
  609.     if ( !timed && !loop && ( sec_count > (double) fileplayingtime - out_time)) {
  610. #ifdef DEBUG
  611.   fprintf(stderr, "fading out\n");
  612. #endif
  613.       fading_in = FALSE;
  614.       fading_out = TRUE;
  615.     }
  616.        
  617.     if (fading_in) {
  618.       attenuatesamps( sampbuf, samp_wordsize, samples_read, secs_per_buf,
  619.              max_level, &fade_level, in_time, 0 );
  620.       if ( fade_level >= 1.0 ) fading_in = FALSE;
  621.     }
  622.     if (fading_out) {
  623.       attenuatesamps( sampbuf, samp_wordsize, samples_read, secs_per_buf,
  624.              max_level, &fade_level, out_time, 1 );
  625.       if ( fade_level <= 0.0 ) {
  626. #ifdef DEBUG
  627.   fprintf(stderr, "fade level is less than zero, exiting \n");
  628. #endif
  629.         fading_out = FALSE;
  630.         done = TRUE;
  631.       }
  632.     }
  633.     if ( ! ( fading_out || fading_in ) && ( max_level != 1.0 ))
  634.       attenuatesamps( sampbuf, samp_wordsize, samples_read, secs_per_buf,
  635.              max_level, &fade_level, out_time, 2 );
  636.  
  637.  
  638.         ALwritesamps(audio_port, sampbuf, samples_read);
  639.  
  640.     if (caught_sigint) {
  641.         done++;
  642. #ifdef DEBUG
  643.         fprintf(stderr, "caught_sigint\n");
  644. #endif
  645.     }
  646.  
  647. /*   THIS DOES NOT WORK, MAYBE SOMEDAY
  648.     if (paused) {
  649.         if (sproced) {
  650. #ifdef DEBUG
  651.   fprintf(stderr, "pausing... ");
  652. #endif
  653.         while(paused) {}
  654. #ifdef DEBUG
  655.   fprintf(stderr, "done\n");
  656. #endif
  657.         }
  658.     }
  659. */
  660.  
  661.  
  662.         if (shortread)
  663.         {
  664.           /*
  665.            * allow the audio buffer to drain
  666.            */
  667.             while(ALgetfilled(audio_port) > 81920) {
  668.                sginap(1);
  669.             }
  670.         if (loop) 
  671.           goto top;
  672.         else
  673.           done = 1;
  674.  
  675.     }
  676.     if (done) {
  677.         while(ALgetfilled(audio_port) > 0) {
  678.         sginap(1);
  679.         }
  680.         sginap(10);
  681.         return(0);
  682.     }
  683.     }
  684.  
  685.     /*
  686.      * play the leftovers
  687.      */
  688.     samp_count  += leftover_samps;
  689.     frame_count += leftover_frames;
  690.     sec_count   += ((double)leftover_frames) * secs_per_frame;
  691.     if (verbose && leftover_samps>0) 
  692.     {
  693.         printf("        %d sample frames  %6.3f secs\n",
  694.                frame_count, sec_count); 
  695.     }
  696.     if ((frames_read = 
  697.        (int) AFreadframes(audio_file, AF_DEFAULT_TRACK, sampbuf, 
  698.                                         leftover_frames)) < leftover_frames)
  699.     {
  700.         if (!quiet)
  701.         { 
  702.             fprintf(stderr, 
  703.          "%s: warning short read for %s: expected %d frames, got %d frames\n",
  704.                     myname, filename, leftover_frames, frames_read);
  705.         }
  706.  
  707.     }
  708.     samples_read = frames_read * samps_per_frame;
  709.  
  710.  
  711.     if ( timed && ( sec_count - in_time > play_time )) {
  712.       fading_in = FALSE;
  713.       fading_out = TRUE;
  714.     }
  715.  
  716.     if ( !timed && !loop && ( sec_count > (double) fileplayingtime - out_time)) {
  717. #ifdef DEBUG
  718.   fprintf(stderr, "fading out 2\n");
  719. #endif
  720.       fading_in = FALSE;
  721.       fading_out = TRUE;
  722.     }
  723.  
  724.     if (fading_in) {
  725.       attenuatesamps( sampbuf, samp_wordsize, samples_read, secs_per_buf,
  726.              max_level, &fade_level, in_time, 0 );
  727.       if ( fade_level >= 1.0 ) fading_in = FALSE;
  728.     }
  729.     if (fading_out) {
  730.       attenuatesamps( sampbuf, samp_wordsize, samples_read, secs_per_buf,
  731.              max_level, &fade_level, out_time, 1 );
  732.       if ( fade_level <= 0.0 ) {
  733.     fading_out = FALSE;
  734.     done = TRUE;
  735.       }
  736.     }
  737.     if ( ! ( fading_out || fading_in ) && ( max_level != 1.0 ))
  738.       attenuatesamps( sampbuf, samp_wordsize, samples_read, secs_per_buf,
  739.              max_level, &fade_level, out_time, 2 );
  740.  
  741.     ALwritesamps(audio_port, sampbuf, samples_read);
  742.  
  743.     /*
  744.      * allow the audio buffer to drain
  745.      */
  746.     while(ALgetfilled(audio_port) > 81920) {
  747.        sginap(1);
  748.     }
  749.     if (loop) goto top;
  750.  
  751.     while(ALgetfilled(audio_port) > 0) {
  752.        sginap(1);
  753.     }
  754.     sginap(10);
  755.     return(0);
  756. }
  757.  
  758. void
  759. PlayClass::setVerbose(int i)
  760. {
  761.     verbose = i;
  762. }
  763.  
  764. void
  765. PlayClass::setFilename(char *fname)
  766. {
  767.     filename = fname;
  768. }
  769.  
  770. void
  771. PlayClass::setQuiet(int i)
  772. {
  773.     quiet = i;
  774. }
  775.  
  776. void
  777. PlayClass::setRude(int i)
  778. {
  779.     rude = i;
  780. }
  781.  
  782. void
  783. PlayClass::setLoop(short i)
  784. {
  785.     loop = i;
  786. }
  787.  
  788. void
  789. PlayClass::setTime(double secs)
  790. {
  791.     play_time = secs;
  792.     timed = TRUE;
  793. }
  794.  
  795. void
  796. PlayClass::setInTime(double secs)
  797. {
  798.     if (secs == 0.0) {
  799.     fading_in = FALSE;
  800.     in_time = 0.0;
  801.     } else {
  802.     fading_in = TRUE;
  803.     in_time = secs;
  804.     }
  805.     
  806. }
  807.  
  808. void
  809. PlayClass::setOutTime(double secs)
  810. {
  811.     out_time = secs;
  812. }
  813.  
  814.  
  815. void PlayClass::setMaxOutputLevel(double lvl)
  816. {
  817.     max_level = lvl;
  818. }
  819.  
  820. void PlayClass::setNoDone(short nd)
  821. {
  822.     NoDone = nd;
  823. }
  824.  
  825. short PlayClass::getIsLive()
  826. {
  827.     return isLive;
  828. }
  829.  
  830. short PlayClass::donep()
  831. {
  832.     if (NoDone) return FALSE;
  833.     else return isDone;
  834. }
  835.  
  836. void
  837. PlayClass::setCallback(PlayClassCB *Callback, void *d)
  838. {
  839. #ifdef DEBUG
  840.     fprintf(stderr, "setCallback\n");
  841. #endif
  842.     doneCallback = Callback;
  843.     userData  = d;
  844. }
  845.  
  846.  
  847. int
  848. PlayClass::start()
  849. {
  850.  
  851.     short hasAudio = FALSE;
  852.   
  853.     if (filename == NULL) return -1;
  854.  
  855.     inventory_t* invry_p;
  856.  
  857.     while((invry_p = getinvent()) != 0) {
  858.     if (invry_p->inv_class == INV_AUDIO) {
  859.       hasAudio = TRUE;
  860.       break;
  861.         }
  862.     }
  863.  
  864.     setinvent();
  865.     endinvent();
  866.  
  867.  
  868.     if (!hasAudio) return -1;
  869.     // this is a quick check to see if there is an audio port available
  870.     ALconfig conf = ALnewconfig();
  871.     ALport   prt;
  872.     if ( (prt = ALopenport( "noname", "w", conf )) != NULL ) {
  873.         // Close the audio port. We only opened it to check 
  874.         // if it was available.
  875.         ALcloseport(prt);
  876.     } else {
  877. #ifdef DEBUG
  878.   fprintf(stderr, "all ports in use, I wasn't able to open a new one\n");
  879. #endif
  880.             audio_pid = -1;
  881.         return -1;
  882.     }
  883.       
  884. #ifdef DEBUG
  885.     fprintf(stderr, "start() filename = %s\n", filename);
  886. #endif
  887.    /*
  888.     *    Use the sproc(2) call to create an audio thread. The audio
  889.     *    thread begins execution at the do_audio entry point. The 
  890.     *    second argument to sproc, PR_SALL, allows the two processes
  891.     *    to share all attributes. See the manual page for the sproc(2)
  892.     *    system call for more details.
  893.     */
  894.     audio_pid =
  895.       sproc((void (*)(void *))&PlayClass::go, PR_SALL, (void *) this);
  896.    if (audio_pid < 0)
  897.    {
  898.        fprintf(stderr, "unable to create audio thread...aborting.\n");
  899.        return -1;
  900.    }
  901. #ifdef DEBUG
  902.      fprintf(stderr, "returning 1, audio_pid = %d\n", audio_pid);
  903. #endif
  904.    sproced = TRUE;
  905.    return 1;
  906.  
  907. }
  908.  
  909. void PlayClass::go(void *obj)
  910. {
  911. #ifdef DEBUG
  912.     fprintf(stderr, "go()\n");
  913. #endif
  914.     PlayClass *objPtr = (PlayClass *) obj;
  915.  
  916.     objPtr->beginPlaying();
  917. #ifdef DEBUG
  918.     fprintf(stderr, "return from beginPlaying()\n");
  919.     fprintf(stderr, "process = %d\n", objPtr->audio_pid);
  920. #endif
  921. }
  922.  
  923. void
  924. PlayClass::fadeOut()
  925. {
  926. #ifdef DEBUG
  927.   fprintf(stderr, "PlayClass::fadeOut()\n");
  928. #endif
  929.     if (out_time > 0.0) {
  930.     fading_out = TRUE;
  931.     fading_in = FALSE;
  932.     return;
  933.     } else {
  934.     stop();
  935.     }
  936. }
  937.  
  938. void
  939. PlayClass::pause()
  940. {
  941.     paused = TRUE;
  942. }
  943.  
  944. void
  945. PlayClass::unpause()
  946. {
  947.     paused = FALSE;
  948. }
  949.  
  950. void
  951. PlayClass::stop()
  952. {
  953.  
  954. #ifdef DEBUG
  955.       fprintf(stderr, "stop()\n");
  956. #endif
  957.       caught_sigint = 1;
  958. #ifdef DEBUG
  959.       fprintf(stderr, "waiting...");
  960. #endif
  961. //      pid_t pid;
  962. //      int status;
  963. //      pid = wait(&status);
  964.     if (audio_pid != -1) {
  965.     union wait waitStatus;
  966.     (void) waitpid(audio_pid, (int *) (&waitStatus), 0);
  967.     }
  968.  
  969. #ifdef DEBUG
  970.       fprintf(stderr, "done.\n");
  971. #endif
  972.     caught_sigint = 0;
  973.     isLive = FALSE;
  974. }
  975.  
  976.  
  977.  
  978. /*
  979.  * application-defined silent error reporting routine
  980.  * for Audio Library
  981.  */
  982. static void
  983. quietALerror(long code, const char *desc, ...)
  984. {
  985. }
  986.  
  987. /*
  988.  * application-defined silent error reporting routine
  989.  * for Audio File Library
  990.  */
  991. static void
  992. quietAFerror(long code, const char *desc)
  993. {
  994. }
  995.